/*
 * File: TriperestUser.java Author: Robert Bittle <guywithnose@gmail.com>
 */
package triperest;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import triperest.Trip;

/**
 * The Class TriperestUser.
 */
public class TriperestUser implements DataObject {

	/** The user cookie. */
	private String userCookie = null;

	/** The Google id. */
	private String GoogleId;

	/** The name. */
	private String name;

	/** The trips. */
	private ArrayList<Trip> trips = new ArrayList<Trip>();

	/** The is temp. */
	private boolean isTemp = false;

	/**
	 * Instantiates a new triperest user.
	 * 
	 * @param req
	 *            the req
	 */
	public TriperestUser(HttpServletRequest req) {
		if (getUserInfo() != null) {
			GoogleId = getUserInfo().getUserId();
			if (!load())// If the user does not exist yet, then save it.
				save();
		} else {
			isTemp = true;
			if (hasUserCookie(req)) {
				GoogleId = getUserCookie(req);
				if (!load())// If the user does not exist yet, then save it.
					save();
			} else {
				GoogleId = "TEMPID" + new Date().getTime();
			}
		}
	}

	/**
	 * Gets the user info.
	 * 
	 * @return the user info
	 */
	public static User getUserInfo() {
		UserService userservice = UserServiceFactory.getUserService();
		User user = userservice.getCurrentUser();
		return user;
	}

	/**
	 * Gets the id.
	 * 
	 * @return the id
	 */
	public String getId() {
		return GoogleId;
	}

	/**
	 * Gets the name.
	 * 
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Sets the name.
	 * 
	 * @param Name
	 *            the new name
	 */
	public void setName(String Name) {
		name = Name;
	}

	/**
	 * Gets the trips.
	 * 
	 * @return the trips
	 */
	public ArrayList<Trip> getTrips() {
		return trips;
	}

	/**
	 * Adds the trip.
	 * 
	 * @param trip
	 *            the trip
	 */
	public void addTrip(Trip trip) {
		trips.add(trip);
	}

	/**
	 * Removes the trip.
	 * 
	 * @param trip
	 *            the trip
	 */
	public void removeTrip(Trip trip) {
		if (trips.contains(trip.getId())) {
			trips.remove(trip.getId());
		}
	}

	/**
	 * Clear trips.
	 */
	public void clearTrips() {
		trips.clear();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see triperest.DataObject#delete()
	 */
	@Override
	public boolean delete() {
		try {
			if (DataConnection.connect()) {
				String statement = "delete from user where user_id = ?";
				PreparedStatement stmt = DataConnection.getConnection()
						.prepareStatement(statement);
				stmt.setString(1, GoogleId);
				int success = 2;
				stmt.executeUpdate();
				Iterator<Long> j = loadTripIds().iterator();
				while (j.hasNext()) {
					deleteTripId(j.next());
				}
				return success == 1;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see triperest.DataObject#save()
	 */
	@Override
	public boolean save() {
		try {
			if (DataConnection.connect()) {
				String statement = "select name from user where user_id = ?";
				PreparedStatement stmt = DataConnection.getConnection()
						.prepareStatement(statement);
				stmt.setString(1, GoogleId);
				ResultSet results = stmt.executeQuery();
				if (results.next()) {
					return update();
				}
				return insert();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * Update.
	 * 
	 * @return true, if successful
	 * @throws SQLException
	 *             the SQL exception
	 */
	private boolean update() throws SQLException {
		if (DataConnection.connect()) {
			String statement = "update user set name = ? where user_id = ?";
			PreparedStatement stmt = DataConnection.getConnection()
					.prepareStatement(statement);
			stmt.setString(1, name);
			stmt.setString(2, GoogleId);
			int success = 2;
			stmt.executeUpdate();
			saveTrips();
			return success == 1;
		}
		return false;
	}

	/**
	 * Update.
	 * 
	 * @return true, if successful
	 * @throws SQLException
	 *             the sQL exception
	 */
	private boolean insert() throws SQLException {
		if (DataConnection.connect()) {
			String statement = "INSERT INTO user (user_id, name) VALUES ( ? , ? )";
			PreparedStatement stmt = DataConnection.getConnection()
					.prepareStatement(statement);
			stmt.setString(1, GoogleId);
			stmt.setString(2, name);
			int success = 2;
			stmt.executeUpdate();
			saveTrips();
			return success == 1;
		}
		return false;
	}

	/**
	 * Save trips.
	 * 
	 * @throws SQLException
	 *             the sQL exception
	 */
	private void saveTrips() throws SQLException {
		ArrayList<Long> tripIds = loadTripIds();
		Iterator<Trip> i = trips.iterator();
		while (i.hasNext()) {
			Trip trip = i.next();
			trip.save();
			if (tripIds.contains(trip.getId())) {
				tripIds.remove(trip.getId());
			} else {
				saveTripId(trip.getId());
			}
		}
		Iterator<Long> j = tripIds.iterator();
		while (j.hasNext()) {
			deleteTripId(j.next());
		}
	}

	/**
	 * Save trip id.
	 * 
	 * @param Id
	 *            the id
	 * @throws SQLException
	 *             the sQL exception
	 */
	private void saveTripId(long Id) throws SQLException {
		if (DataConnection.connect()) {
			String statement = "INSERT INTO user_trip (user_id, trip_id) VALUES ( ? , ? )";
			PreparedStatement stmt = DataConnection.getConnection()
					.prepareStatement(statement);
			stmt.setString(1, GoogleId);
			stmt.setLong(2, Id);
			stmt.executeUpdate();
		}
	}

	/**
	 * Delete trip id.
	 * 
	 * @param Id
	 *            the id
	 * @throws SQLException
	 *             the sQL exception
	 */
	private void deleteTripId(long Id) throws SQLException {
		if (DataConnection.connect()) {
			String statement = "delete from user_trip where user_id = ? and trip_id = ?";
			PreparedStatement stmt = DataConnection.getConnection()
					.prepareStatement(statement);
			stmt.setString(1, GoogleId);
			stmt.setLong(2, Id);
			stmt.executeUpdate();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see triperest.DataObject#load()
	 */
	@Override
	public boolean load() {
		try {
			if (DataConnection.connect()) {
				String statement = "select name from user where user_id = ?";
				PreparedStatement stmt = DataConnection.getConnection()
						.prepareStatement(statement);
				stmt.setString(1, GoogleId);
				ResultSet results = stmt.executeQuery();
				if (results.next()) {
					name = results.getString("name");
					Iterator<Long> i = loadTripIds().iterator();
					while (i.hasNext()) {
						trips.add(new Trip(i.next()));
					}
					return true;
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * Load trip ids.
	 * 
	 * @return the array list
	 */
	private ArrayList<Long> loadTripIds() {
		ArrayList<Long> tripIds = new ArrayList<Long>();
		try {
			if (DataConnection.connect()) {
				String statement = "select trip_id from user_trip where user_id = ?";
				PreparedStatement stmt = DataConnection.getConnection()
						.prepareStatement(statement);
				stmt.setString(1, GoogleId);
				ResultSet results = stmt.executeQuery();
				while (results.next()) {
					tripIds.add(results.getLong("trip_id"));
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return tripIds;
	}

	/**
	 * Checks if is temp.
	 * 
	 * @return true, if is temp
	 */
	public boolean isTemp() {
		return isTemp;
	}

	/**
	 * Gets the temp cookie.
	 * 
	 * @param req
	 *            the req
	 * @return the temp cookie
	 */
	private String getUserCookie(HttpServletRequest req) {
		if (userCookie == null) {
			Cookie[] cookies = req.getCookies();
			if (cookies != null) {
				for (int i = 0; i < cookies.length; i++) {
					if (cookies[i].getName().equals("user"))
						userCookie = cookies[i].getValue();
				}
			}
		}
		return userCookie;
	}

	/**
	 * Checks for user cookie.
	 * 
	 * @param req
	 *            the req
	 * @return true, if successful
	 */
	private boolean hasUserCookie(HttpServletRequest req) {
		return getUserCookie(req) != null;
	}

}